package com.xmall.product.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmall.define.constants.CommonConstants;
import com.xmall.product.define.dict.LeafStatusEnum;
import com.xmall.product.define.dto.spu.SpuInfoDto;
import com.xmall.product.utils.ConvertUtils;
import com.xmall.product.define.dto.category.CategoryDto;
import com.xmall.product.define.dto.category.CategoryTreeDto;
import com.xmall.product.entity.Category;
import com.xmall.product.mapper.CategoryMapper;
import com.xmall.product.define.request.category.CategoryUpdateRequest;
import com.xmall.product.service.ICategoryService;
import com.xmall.utils.XmallUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xmall
 * @since 2023-11-02
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {

    /**
     * 设置分类信息
     */
    @Override
    public void setSpuInfo(SpuInfoDto spuInfoDto) {
        XmallUtils.notNull(spuInfoDto.getCategoryId());
        Category category = this.getById(spuInfoDto.getCategoryId());
        XmallUtils.notNull(category);

        spuInfoDto.setCategoryName(category.getName());
        spuInfoDto.setCategoryBreadcrumbName(String.join(" / ", this.hierarchyNameList(spuInfoDto.getCategoryId())));

    }

    /**
     * 分类树
     */
    @Override
    public List<CategoryTreeDto> treeList() {
        // TODO 父子结构过滤时，如何展现
        return createTree(this.list());
    }

    /**
     * 子分类列表
     */
    @Override
    public List<CategoryDto> children(Long parentId) {
        String parentName = "";
        // 查询父级名称
        if(parentId != CommonConstants.TOP_PARENT_ID){
            Category parentEntity = this.getById(parentId);
            parentName = null != parentEntity ? parentEntity.getName() : "";
        }

        // 查询子分类
        String finalParentName = parentName;
        return this.list(new QueryWrapper<Category>().eq("parent_id", parentId)).stream().map(entity -> {
            CategoryDto dto = ConvertUtils.CategoryModule.INSTANCE.toDto(entity);
            dto.setParentName(finalParentName);
            dto.setHasChildren(entity.getLeaf() == LeafStatusEnum.NO.getVal());
            return dto;
        }).sorted(Comparator.comparing(CategoryDto::getSort)).collect(Collectors.toList());
    }

    /**
     * 详情
     */
    @Override
    public CategoryDto info(Long id) {
        Category entity = this.getById(id);
        XmallUtils.notNull(entity);
        return ConvertUtils.CategoryModule.INSTANCE.toDto(entity);
    }

    /**
     * 编辑
     */
    @Override
    public void updateEntity(CategoryUpdateRequest request) {
        Category entity = this.getById(request.getId());
        if(null != entity){
            Category updateEntity = new Category();
            updateEntity.setId(request.getId());
            updateEntity.setName(request.getName());
            updateEntity.setSort(request.getSort());
            this.updateById(updateEntity);
        }
    }

    /**
     * 新增
     */
    @Transactional
    @Override
    public void saveEntity(CategoryUpdateRequest request) {
        // 生成唯一标识
        String uuid = IdUtil.simpleUUID();

        // 父级ID为0
        if(request.getParentId() == CommonConstants.TOP_PARENT_ID){
            Category entity = new Category();
            entity.setParentId(CommonConstants.TOP_PARENT_ID);
            entity.setLevel(CommonConstants.DEFAULT_NEXT_ADD_LEVEL);
            entity.setName(request.getName());
            entity.setSort(request.getSort());
            entity.setLeaf(LeafStatusEnum.YES.getVal());
            entity.setUuid(uuid);
            entity.setPath(uuid);
            this.save(entity);
            return;
        }

        // 父级ID不为0
        Category parentEntity = this.getById(request.getParentId());
        XmallUtils.notNull(parentEntity);

        // 更新父级叶子节点状态
        if(parentEntity.getLeaf() == LeafStatusEnum.YES.getVal()){
            Category updateEntity = new Category();
            updateEntity.setId(parentEntity.getId());
            updateEntity.setLeaf(LeafStatusEnum.NO.getVal());
            this.updateById(updateEntity);
        }

        Category entity = new Category();
        entity.setParentId(parentEntity.getId());
        entity.setLevel(parentEntity.getLevel() + CommonConstants.DEFAULT_NEXT_ADD_LEVEL);
        entity.setName(request.getName());
        entity.setSort(request.getSort());
        entity.setLeaf(LeafStatusEnum.YES.getVal());
        entity.setUuid(uuid);
        entity.setPath(parentEntity.getPath() + "," + uuid);
        this.save(entity);
    }

    /**
     * 级联删除
     */
    @Override
    public void deleteEntity(Long id) {
        //TODO 检查是否已被引用
        Category entity = this.getById(id);
        XmallUtils.notNull(entity);
        this.baseMapper.deleteCascade(entity.getUuid());
    }

    /**
     * 获取分类名称列表（当前分类及所有父级）
     */
    @Override
    public List<String> hierarchyNameList(Long id) {
        Category category = this.getById(id);
        XmallUtils.notNull(category);
        return this.list(new QueryWrapper<Category>().in("uuid", category.getPath().split(","))).stream()
                .sorted(Comparator.comparing(Category::getLevel))
                .map(item -> item.getName()).collect(Collectors.toList());
    }

    /**
     * 获取分类ID（当前分类及所有父级）
     */
    @Override
    public List<Long> hierarchyIdList(Long id) {
        Category category = this.getById(id);
        XmallUtils.notNull(category);

        List<Category> categoryList = this.list(new QueryWrapper<Category>().in("uuid", category.getPath().split(",")));
        XmallUtils.notEmpty(categoryList);
        return categoryList.stream().map(entity -> entity.getId()).collect(Collectors.toList());
    }

    /**
     * 获取分类ID（当前分类及所有子类）
     */
    @Override
    public List<Long> childIdList(Long id) {
        Category category = this.getById(id);
        XmallUtils.notNull(category);
        return this.list(new QueryWrapper<Category>().like("path", category.getUuid())).stream()
            .map(entity -> entity.getId()).collect(Collectors.toList());
    }

    /**
     * 生出树结构
     */
    public List<CategoryTreeDto> createTree(List<Category> categories){
        return categories.stream()
                .filter(entity -> entity.getParentId() == 0)
                .map(entity -> {
                    CategoryTreeDto dto = new CategoryTreeDto();
                    BeanUtils.copyProperties(entity, dto);
                    dto.setChildren(children(dto.getId(), categories));
                    return dto;
                })
                .sorted(Comparator.comparing(CategoryTreeDto::getSort))
                .collect(Collectors.toList());
    }

    private List<CategoryTreeDto> children(Long parentId, List<Category> categories){
        return categories.stream().filter(entity -> entity.getParentId() == parentId).map(entity -> {
            CategoryTreeDto dto = new CategoryTreeDto();
            BeanUtils.copyProperties(entity, dto);
            dto.setChildren(children(dto.getId(), categories));
            return dto;
        })
        .sorted(Comparator.comparing(CategoryTreeDto::getSort))
        .collect(Collectors.toList());
    }
}
